//
// Created by jinbang.li on 2023/5/21.
//
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavcodec/jni.h>
}
#include "../Log/OpLog.h"
#include "OpFFDecode.h"

void OpFFDecode::InitHard(void *vm) {
    av_jni_set_java_vm(vm,0);
}

/**
 * 打开解码器
 * @param opParameter
 * @return
 */
bool OpFFDecode::Open(OpParameter opParameter,bool isHard){
    if (!opParameter.parameters) return false;
    AVCodecParameters *parameters = opParameter.parameters;
    AVCodec *codec = avcodec_find_decoder(parameters->codec_id);
    if (isHard){
        codec = avcodec_find_decoder_by_name("h264_mediacodec");
    }
    if (!codec){
        OPLOGE("avcodec_find_decoder failed codec_id=%d,isHard=%d",parameters->codec_id,isHard);
        return false;
    }
    codecContext = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codecContext,parameters);
    codecContext->thread_count = 8;
    int re = avcodec_open2(codecContext,0,0);
    if (re != 0){
        char buf[1024] = {0};
        av_strerror(re,buf,sizeof(buf) - 1);
        return false;
    }
    if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO){
        this->isAudio = false;
    } else{
        this->isAudio = true;
    }
    return true;
}
/**
 * 发送数据到线程解码
 * @param pkt
 * @return
 */
bool OpFFDecode::SendPacket(OpData pkt){
    if (pkt.size <= 0 || !pkt.data) return false;
    if (!codecContext){
        return false;
    }
    int re = avcodec_send_packet(codecContext,(AVPacket *)pkt.data);
    if (re != 0){
        return false;
    }
    return true;
}
/**
 * 获取解码的结果
 * @return
 */
OpData OpFFDecode::RecvFrame() {
    if (!codecContext){
        return OpData();
    }
    if (!frame){
       frame = av_frame_alloc();
    }
    int  re = avcodec_receive_frame(codecContext,frame);
    if (re != 0){
        return OpData();
    }
    OpData data;
    data.data = (unsigned char *)frame;
    if (codecContext->codec_type == AVMEDIA_TYPE_VIDEO){
        data.size = (frame->linesize[0] + frame->linesize[1] + frame->linesize[2]) * frame->height;
        data.width = frame->width;
        data.height = frame->height;
    } else{
        //样本采样数 单通道样本数 通道数
        data.size = av_get_bytes_per_sample((AVSampleFormat) frame->format) * frame->nb_samples * 2;
    }
    memcpy(data.datas,frame->data, sizeof(data.datas));
    return data;
}